package com.atguigu.spzx.sms.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.atguigu.spzx.common.consts.SpzxConsts;
import com.atguigu.spzx.model.exception.SpzxException;
import com.atguigu.spzx.model.vo.common.ResultCodeEnum;
import com.atguigu.spzx.sms.config.SmsProperties;
import com.atguigu.spzx.sms.service.SmsService;
import com.atguigu.spzx.sms.util.HttpUtils;
import com.atguigu.spzx.common.util.RegexValidateUtils;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@EnableConfigurationProperties(SmsProperties.class)
@Service
public class SmsServiceImpl implements SmsService {
    @Resource
    StringRedisTemplate stringRedisTemplate;
    @Override
    public void sendMsg(String phone, Integer type) {
        if(type==null){
            sendRegisterCode(phone);
        }else if(type.intValue() == 1){

        }else if(type.intValue()==2){

        }
    }
    //发送短信验证码业务方法
    private void sendRegisterCode(String phone) {
        //1、校验手机号码格式
        boolean checkCellphone = RegexValidateUtils.checkCellphone(phone);
        if(!checkCellphone){
            throw new SpzxException(ResultCodeEnum.PHONE_ERROR);
        }
        //2、校验验证码发送的频率：如果手机号2分钟内重复获取、一天内获取次数超过5次 ，拒绝发送验证码
        //"spzx:sms:count:"+phone
        if(stringRedisTemplate.hasKey("spzx:sms:count:"+phone)){
            throw new SpzxException(ResultCodeEnum.SEND_MSG_COUNT_ERROR);
        }

        //"spzx:sms:limit:" + phone
        String limitStr = stringRedisTemplate.opsForValue().get("spzx:sms:limit:" + phone);
        if(!StringUtils.isEmpty(limitStr) && Integer.parseInt(limitStr)>=5){
            throw new SpzxException(ResultCodeEnum.SEND_MSG_LIMIT_ERROR);
        }
        //3、发送验证码
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + SmsProperties.APPCODE);
        //根据API的要求，定义相对应的Content-Type
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        //生成4为长度的数字组成的字符串
        String code = RandomUtil.randomNumbers(4);
        Map<String, String> bodys = new HashMap<String, String>();
        bodys.put("content", "code:"+code);
        bodys.put("template_id", SmsProperties.TEMPLATE_ID);  //注意，CST_ptdie100该模板ID仅为调试使用，调试结果为"status": "OK" ，即表示接口调用成功，然后联系客服报备自己的专属签名模板ID，以保证短信稳定下发
        bodys.put("phone_number", phone);

        try {
            HttpResponse response = HttpUtils.doPost(SmsProperties.HOST, SmsProperties.PATH,
                    SmsProperties.METHOD, headers, querys, bodys);
//            System.out.println(response.toString());
            int statusCode = response.getStatusLine().getStatusCode();
            if(statusCode!=200){
                throw new SpzxException(ResultCodeEnum.SEND_MSG_ERROR);
            }
            //获取响应体json字符串
            String result = EntityUtils.toString(response.getEntity());
            Map map = JSON.parseObject(result, Map.class);
            if(!"OK".equals(map.get("status"))){
                throw new SpzxException(ResultCodeEnum.SEND_MSG_ERROR);
            }
            //短信发送成功
            //4、缓存验证码到redis，注册时校验
            stringRedisTemplate.opsForValue().set(SpzxConsts.SPZX_CODE_PREFIX +phone , code , 20 , TimeUnit.MINUTES);
            //redis+LUA脚本
            //5、更新验证码发送的次数：
            // 2分钟内不能重复发送
            stringRedisTemplate.opsForValue().set("spzx:sms:count:"+phone , "1" , 2 , TimeUnit.MINUTES);
            //1天内只能发送五次验证码:    redis的incr 当键不存在时，使用0自增
            Long limit = stringRedisTemplate.opsForValue().increment("spzx:sms:limit:" + phone);
            if(limit.longValue()==1){
                //表示第一次自增
                stringRedisTemplate.expire("spzx:sms:limit:" + phone,1,TimeUnit.DAYS);
            }

        } catch (Exception e) {
            throw new SpzxException(ResultCodeEnum.SEND_MSG_ERROR,e);
        }
    }
}
